'''
Created on 13/05/2013

@author: cristian
'''
from flask import Flask, session, redirect, url_for, escape, request, Response
from pm import app
from pm.models.Relaciones import Relaciones
from pm.models.Items import Items
from pm.models.Fases import Fases
from pm.models.Proyectos import Proyectos
from . import jsonifiedview
from pm.database import db
from pm.views import ensureParams
from pm.views.MetodosRelacionesViews import existeRelacion 
from pm.views.MetodosRelacionesViews import getHijos
from pm.views.MetodosRelacionesViews import tieneCiclo
from pm.views.MetodosRelacionesViews import recorrerAtras
from pm.views.MetodosRelacionesViews import recorrerAdelante
from sqlalchemy.orm.exc import NoResultFound
from pm.models.HistorialItem import HistorialItem
from pm.models.HistorialDetalle import HistorialDetalle
import simplejson

@app.route('/relaciones/padrehijoitem', methods=['GET', 'POST']) 
@jsonifiedview
def relacionPadreHijoItem():
    '''
    Relaciona un item padre con el hijo
    
    '''
    
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_origen','id_destino']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    
    try:
        id_origen= int(str(params['id_origen']))
        id_destino= int(str(params['id_destino']))
        item_origen = Items.query.filter(Items.id_item== id_origen).one()
        item_destino = Items.query.filter(Items.id_item == id_destino).one()
        
        rel =existeRelacion(id_origen, id_destino)
        if rel != None:
            response = {"success":False,"msg":"La relacion ya existe!!"}
            return response 
        if  tieneCiclo(getHijos(id_destino), id_origen):
            response = { "success": False , "msg":"La relacion con este item genera un ciclo!!" }
            return response 
        
        relacionPadreHijo = Relaciones(id_origen,id_destino,1,True, item_origen.nombre,item_destino.nombre)
        db.session.add(relacionPadreHijo) 
        db.session.commit()
        historialItemOri = HistorialItem.query.filter(HistorialItem.id_item==item_origen.id_item).filter(HistorialItem.version ==item_origen.version).one()
        historialItemDest = HistorialItem.query.filter(HistorialItem.id_item==item_destino.id_item).filter(HistorialItem.version ==item_destino.version).one()
        histDetOrig = HistorialDetalle(relacionPadreHijo.id_relacion,historialItemOri.id_historial_item,relacionPadreHijo.activo)
        db.session.add(histDetOrig)
        db.session.commit()
        histDetDest = HistorialDetalle(relacionPadreHijo.id_relacion,historialItemDest.id_historial_item, relacionPadreHijo.activo)
        db.session.add(histDetDest)
        db.session.commit()
        
       
        response ={"success" : True , "msg" : "Creacion exitosa de la Relacion!!"} 
        return response
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : str(e)}
        return response 
    
    
    
@app.route('/relaciones/antecesorsucesoritem', methods=['GET', 'POST']) 
@jsonifiedview
def relacionAntecesorSucesorItem():    
    
    """
        Crea una relacion Antecesor-Sucesor entre dos items
        @param id_origen: identificador del item origen
        @param id_destino: identificador del item destino 
       
    """
    
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_origen','id_destino']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    
    try:
        id_origen= int(str(params['id_origen']))
        id_destino= int(str(params['id_destino']))
        item_origen = Items.query.filter(Items.id_item== id_origen).one()
        item_destino = Items.query.filter(Items.id_item == id_destino).one()
        
        rel =existeRelacion(id_origen, id_destino)
        if rel != None:
            response = {"success":False,"msg":"La relacion ya existe!!"}
            return response 
             
        relacionAntecesorSucesor = Relaciones(id_origen,id_destino,2,True, item_origen.nombre,item_destino.nombre)
        db.session.add(relacionAntecesorSucesor) 
        db.session.commit()
        historialItemOri = HistorialItem.query.filter(HistorialItem.id_item==item_origen.id_item).filter(HistorialItem.version ==item_origen.version).one()
        historialItemDest = HistorialItem.query.filter(HistorialItem.id_item==item_destino.id_item).filter(HistorialItem.version ==item_destino.version).one()
        histDetOrig = HistorialDetalle(relacionAntecesorSucesor.id_relacion,historialItemOri.id_historial_item,relacionAntecesorSucesor.activo)
        db.session.add(histDetOrig)
        db.session.commit()
        histDetDest = HistorialDetalle(relacionAntecesorSucesor.id_relacion,historialItemDest.id_historial_item, relacionAntecesorSucesor.activo)
        db.session.add(histDetDest)
        db.session.commit()
        response ={"success" : True , "msg" : "Creacion exitosa de la Relacion!!"} 
        return response
    except Exception, e:
        print e
        db.session.rollback()
        response ={"success" : False , "msg" : str(e)}
        return response 
    
    
@app.route('/relaciones/listaritemshijos', methods=['GET', 'POST'])
@jsonifiedview
def listarItemHijos():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    resp = []
    itemHijo = Relaciones.query.filter(Relaciones.id_origen == params['id'])
    for ih in itemHijo:
        if (ih.tipo == 1 and ih.activo==True):
            item= Items.query.filter(Items.id_item ==ih.id_destino).one()
            resp.append(item)
    return resp

@app.route('/relaciones/listaritemssucesores', methods=['GET', 'POST'])
@jsonifiedview
def listarItemSucesores():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    resp = []
    itemSucesor = Relaciones.query.filter(Relaciones.id_origen == params['id'])
    for iS in itemSucesor:
        if (iS.tipo == 2 and iS.activo==True):
            item= Items.query.filter(Items.id_item ==iS.id_destino).one()
            resp.append(item)
    return resp   
    
@app.route('/relaciones/listaritemsPadres', methods=['GET', 'POST'])
@jsonifiedview
def listarItemPadres():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    resp = []
    itemPadre = Relaciones.query.filter(Relaciones.id_destino == params['id'])
    for ip in itemPadre:
        if (ip.tipo == 1 and ip.activo==True):
            item= Items.query.filter(Items.id_item ==ip.id_origen).one()
            resp.append(item)
    return resp

@app.route('/relaciones/listaritemsantecesores', methods=['GET', 'POST'])
@jsonifiedview
def listarItemAntecesores():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    resp = []
    itemAntecesor = Relaciones.query.filter(Relaciones.id_destino == params['id'])
    for ia in itemAntecesor:
        if (ia.tipo == 2 and ia.activo==True):
            item= Items.query.filter(Items.id_item ==ia.id_origen).one()
            resp.append(item)
    return resp 

@app.route('/relaciones/listarposibleshijos', methods=['GET', 'POST'])
@jsonifiedview
def listarItemPosiblesHijos():
    """
        Lista los items de una fase particular que esten aprobados para ser relacionados como hijos de una relacion
        @param id_item: id del item que sera padre de la relacion
        
    """
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_item']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    
    id_item= int(str(params['id_item']))
    item= Items.query.filter(Items.id_item == id_item).one()
    id_fase= item.id_fase
    if item.estado != 2:
        response ={"success" : False , "msg" : "El item no esta aprobado para realizar la relacion!!"} 
        return response
  
    items= Items.query.filter(Items.id_fase==id_fase).all()
    listaHijos= []
    for i in items:
        if (i.id_item != id_item and i.estado == 2):
            if (existeRelacion(i.id_item, id_item)==None ):
                if (existeRelacion(id_item,i.id_item)==None):
                    if(tieneCiclo(getHijos(i.id_item), id_item)==False):
                        listaHijos.append(i)
    return listaHijos
    
@app.route('/relaciones/listarposiblesAntecesores', methods=['GET', 'POST'])
@jsonifiedview
def listarItemPosiblesAntecesores():
    """
       Lista los items de la fase anterior que pueden ser sus ancestros
       @param id_item: id del item que sera padre de la relacion
        
    """
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_item']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    
    id_item= int(str(params['id_item']))
    item= Items.query.filter(Items.id_item == id_item).one()
    id_fase= item.id_fase
    
    
    if item.estado != 2:
        response ={"success" : False , "msg" : "El item no esta Aprobado para realizar la relacion!!"} 
        return response
    fase= Fases.query.filter(Fases.id_fase== id_fase).one()
    id_proyecto= fase.id_proyecto
    proyecto= Proyectos.query.filter(Proyectos.id_proyecto== id_proyecto).one()
    #cant_Fases_Proyecto= proyecto.cantidad_fases
    listaFasesProyecto= Fases.query.filter(Fases.id_proyecto==proyecto.id_proyecto).all()
    listarAntecesores=[]
    if(fase.posicion!=1):
        #faseAnteriores= Fases.query.filter(Fases.id_proyecto==id_proyecto).all()
        posicion = fase.posicion - 1
        faseAnterior= Fases.query.filter(Fases.id_proyecto==id_proyecto).filter(Fases.posicion==posicion).one()
        itemsFaseAnterior= Items.query.filter(Items.id_fase== faseAnterior.id_fase).all()
        
       
        for ifa in itemsFaseAnterior:
            if ifa.estado==2 or ifa.estado==3:
                if not existeRelacion(ifa.id_item, id_item):
                    listarAntecesores.append(ifa)
        return listarAntecesores
    response ={"success" : False , "msg" : "La Fase Actual no tiene Antecesores!!"} 
    return response
    
@app.route('/relaciones/eliminarrelacion', methods=['GET', 'POST'])
@jsonifiedview
def activarDesactivarRelacion():
    """
       Activa/Desactiva la relacion entre un Padre-Hijo Ancestro-Sucesor
       @param id_origen: identificador del item origen
       @param id_destino: identificador del item destino
       @param activo: indica si la relacion sera True o False
        
    """
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_origen','id_destino','activo']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    id_origen= params['id_origen']
    id_destino= params['id_destino']
    activo= params['activo']
    try:
        item1= Items.query.filter(Items.id_item==id_origen).one()
        item2= Items.query.filter(Items.id_item== id_destino).one()
        if(item2.estado!=2 and item2.estado!=4):
            response ={"success" : False , "msg" : "La relacion no puede ser desactivada!!"} 
            return response
        
        if (item1.estado==6 or item2.estado==6):
            response ={"success" : False , "msg" : "La relacion no puede ser desactivada!!"} 
            return response
       
        relacion = Relaciones.query.filter(Relaciones.id_origen==id_origen).filter(Relaciones.id_destino==id_destino).one()
        historialItemOri = HistorialItem.query.filter(HistorialItem.id_item==item1.id_item).filter(HistorialItem.version ==item1.version).one()
        historialItemDest = HistorialItem.query.filter(HistorialItem.id_item==item2.id_item).filter(HistorialItem.version ==item2.version).one()
        histDetOrig = HistorialDetalle.query.filter(HistorialDetalle.id_historial_item == historialItemOri.id_historial_item).filter(HistorialDetalle.id_relacion == relacion.id_relacion).one()
        histDetOrig.estado_relacion = activo
        db.session.commit()
        histDetDest = HistorialDetalle.query.filter(HistorialDetalle.id_historial_item == historialItemDest.id_historial_item).filter(HistorialDetalle.id_relacion == relacion.id_relacion).one()
        histDetDest.estado_relacion = activo
        db.session.commit()
        relacion= Relaciones.query.filter(Relaciones.id_origen==id_origen).filter(Relaciones.id_destino==id_destino).update({'activo':activo})
        db.session.commit()
        response ={"success" : True , "msg" : "Actualizacion exitosa!!"} 
        return response
    
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : "Ups, ha ocurrido un error" + str(e)}
        return response


@app.route('/relaciones/estadorelacion', methods=['GET', 'POST'])
@jsonifiedview
def obtenerEstadoRelacion():
    """
       obtiene el estado de la relacion
       @param id_origen: identificador del item origen
       @param id_destino: identificador del item destino
       
    """
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_origen','id_destino']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    id_origen= params['id_origen']
    id_destino= params['id_destino']
    try:
        relacion= Relaciones.query.filter(Relaciones.id_origen==id_origen).filter(Relaciones.id_destino==id_destino).one()
        valor= relacion.activo
        response ={"success" : True , "msg" : "Actualizacion exitosa!!","valor":valor} 
        return response
    
    except Exception, e:
        db.session.rollback()
        response ={"success" : False , "msg" : "Ups!! Se ha producido un error al intentar obtener el estado de la relacion!!"}
        return response    

@app.route('/relaciones/calcularimpacto', methods=['GET', 'POST'])
@jsonifiedview
def calcularImpacto():
    """
       Calcula el impacto de un item especifico
       @param id_origen: identificador del item origen
       @param id_destino: identificador del item destino
       @param activo: indica si la relacion sera True o False
        
    """
    params = {'GET':request.args, 'POST':request.form}[request.method]
    response = {}
        
    if not ensureParams(params,['id_item','complejidad']): 
        response ={"success" : False , "msg" : "Parametros Insuficientes!!"} 
        return response
    id_item= params['id_item']
    complejidad= int(str(params['complejidad']))
       
    
        
    visitadoAtras = []
    visitadoAdelante = []
    item= Items.query.filter(Items.id_item==id_item).one()
    fase= Fases.query.filter(Fases.id_fase== item.id_fase).one()
    
    atras = 0
    adelante = 0
    sumaTotal= 0
    sumaCostoTotal=0 + item.costo
    listaID = []
    
    recorrerAtras(id_item, visitadoAtras)
    recorrerAdelante(id_item, visitadoAdelante)
    
    try:
        for va in visitadoAtras:
            itemAtras = Items.query.filter(Items.id_item==va).one()
            atras = atras + itemAtras.complejidad
            sumaCostoTotal= sumaCostoTotal+ itemAtras.costo
            listaID.append(va)
        for vad in visitadoAdelante:
            itemAdelante=Items.query.filter(Items.id_item==vad).one()
            adelante=adelante + itemAdelante.complejidad
            sumaCostoTotal= sumaCostoTotal+ itemAdelante.costo
            listaID.append(vad)
                
        suma = 0
        suma = suma + atras + adelante + complejidad
        response={"success":True,"atras": atras,"adelante":adelante,"suma": suma,"visitadoAtras":visitadoAtras,"visitadoAdelante":visitadoAdelante,"costo": sumaCostoTotal}
        return response
    except Exception, e:
        response ={"success" : False , "msg" : "Ups!! Se ha producido un error al realizar el calculo de Impacto!!"}
        return response 
    


def calcularImpactoSolicitud(id_item):
    """
       Calcula el impacto de un item especifico
       @param id_item: identificador del item origen        
    """
        
    visitadoAtras = []
    visitadoAdelante = []
    item= Items.query.filter(Items.id_item==id_item).one()
    fase= Fases.query.filter(Fases.id_fase== item.id_fase).one()
    
    atras = 0
    adelante = 0
    sumaTotal= 0
    listaID = []
    
    recorrerAtras(id_item, visitadoAtras)
    recorrerAdelante(id_item, visitadoAdelante)
    
    try:
        for va in visitadoAtras:
            itemAtras = Items.query.filter(Items.id_item==va).one()
            atras = atras + itemAtras.complejidad
            listaID.append(va)
        for vad in visitadoAdelante:
            itemAdelante=Items.query.filter(Items.id_item==vad).one()
            adelante=adelante + itemAdelante.complejidad
            listaID.append(vad)
                
        suma = 0
        suma = suma + atras + adelante + item.complejidad
        return suma
    except Exception, e:
        suma=0
        return suma  
    
def calcularImpactoMonetarioSolicitud(id_item):
    """
       Calcula el impacto de un item especifico
       @param id_item: identificador del item origen        
    """
        
    visitadoAtras = []
    visitadoAdelante = []
    item= Items.query.filter(Items.id_item==id_item).one()
    sumaMonetaria= 0 + item.costo    
    recorrerAtras(id_item, visitadoAtras)
    recorrerAdelante(id_item, visitadoAdelante)
    
    try:
        for va in visitadoAtras:
            itemAtras = Items.query.filter(Items.id_item==va).one()
            sumaMonetaria=sumaMonetaria+itemAtras.costo
        for vad in visitadoAdelante:
            itemAdelante=Items.query.filter(Items.id_item==vad).one()
            sumaMonetaria=sumaMonetaria+itemAdelante.costo
        return sumaMonetaria
    except Exception, e:
        sumaMonetaria=0
        return sumaMonetaria  

@app.route('/relaciones/listaritemsantecesoresbyversion', methods=['GET', 'POST'])
@jsonifiedview
def listarItemAntecesoresByVersion():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    
    id_item= int(str(params['id_item']))
    version= int(str(params['version']))
    itemActual = Items.query.filter(Items.id_item==id_item).one()
    
    historial_item= HistorialItem.query.filter(HistorialItem.id_item==id_item).filter(HistorialItem.version==version).one()

    historial_detalle= HistorialDetalle.query.filter(HistorialDetalle.id_historial_item==historial_item.id_historial_item).all()
    
    listaAntecesores=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==2 and relacion_item.nombre_origen!=itemActual.nombre:
            response ={"nombre_origen" : relacion_item.nombre_origen}
            listaAntecesores.append(response)   
    return listaAntecesores
            
@app.route('/relaciones/listaritemssucesoresbyversion', methods=['GET', 'POST'])
@jsonifiedview
def listarItemSucesoresByVersion():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    
    id_item= int(str(params['id_item']))
    version= int(str(params['version']))
    itemActual = Items.query.filter(Items.id_item==id_item).one()
    
    historial_item= HistorialItem.query.filter(HistorialItem.id_item==id_item).filter(HistorialItem.version==version).one()

    historial_detalle= HistorialDetalle.query.filter(HistorialDetalle.id_historial_item==historial_item.id_historial_item).all()
    
    listaSucesores=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==2 and relacion_item.nombre_destino!=itemActual.nombre:
            response ={"nombre_destino" : relacion_item.nombre_destino}
            listaSucesores.append(response)
    return listaSucesores

@app.route('/relaciones/listaritemspadresbyversion', methods=['GET', 'POST'])
@jsonifiedview
def listarItemPadresByVersion():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    
    id_item= int(str(params['id_item']))
    version= int(str(params['version']))
    itemActual = Items.query.filter(Items.id_item==id_item).one()
    
    historial_item= HistorialItem.query.filter(HistorialItem.id_item==id_item).filter(HistorialItem.version==version).one()

    historial_detalle= HistorialDetalle.query.filter(HistorialDetalle.id_historial_item==historial_item.id_historial_item).all()
    
    listaPadres=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==1 and relacion_item.nombre_origen!=itemActual.nombre:
            response ={"nombre_origen" : relacion_item.nombre_origen}
            listaPadres.append(response)
    return listaPadres

@app.route('/relaciones/listaritemshijosbyversion', methods=['GET', 'POST'])
@jsonifiedview
def listarItemHijosByVersion():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    
    id_item= int(str(params['id_item']))
    version= int(str(params['version']))
    
    itemActual = Items.query.filter(Items.id_item==id_item).one()
    
    historial_item= HistorialItem.query.filter(HistorialItem.id_item==id_item).filter(HistorialItem.version==version).one()

    historial_detalle= HistorialDetalle.query.filter(HistorialDetalle.id_historial_item==historial_item.id_historial_item).all()
    
    listaHijos=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==1 and relacion_item.nombre_destino!=itemActual.nombre:
            response ={"nombre_destino" : relacion_item.nombre_destino}
            listaHijos.append(response)
    return listaHijos
    
@app.route('/relaciones/listargrafoversion', methods=['GET', 'POST'])
@jsonifiedview
def listarGrafoByVersion():
    params = {'GET':request.args, 'POST':request.form}[request.method]
    
    id_item= int(str(params['id_item']))
    version= int(str(params['version']))
    
    itemActual = Items.query.filter(Items.id_item==id_item).one()
    
    historial_item= HistorialItem.query.filter(HistorialItem.id_item==id_item).filter(HistorialItem.version==version).one()

    historial_detalle= HistorialDetalle.query.filter(HistorialDetalle.id_historial_item==historial_item.id_historial_item).all()
    
    listaHijos=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==1 and relacion_item.nombre_destino!=itemActual.nombre:
            listaHijos.append(relacion_item.nombre_destino)
    
    listaPadres=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==1 and relacion_item.nombre_origen!=itemActual.nombre:
            listaPadres.append(relacion_item.nombre_origen)    
            
    listaSucesores=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==2 and relacion_item.nombre_destino!=itemActual.nombre:
            listaSucesores.append(relacion_item.nombre_destino)    
    
    listaAntecesores=[]
    for hd in historial_detalle:
        relacion_item=Relaciones.query.filter(Relaciones.id_relacion== hd.id_relacion).one()
        if hd.estado_relacion!=False and relacion_item.tipo==2 and relacion_item.nombre_origen!=itemActual.nombre:
            listaAntecesores.append(relacion_item.nombre_origen) 
    
    response ={"success":True,"item_actual" : itemActual.nombre,"padres":listaPadres, "hijos": listaHijos,"sucesores":listaSucesores,"antecesores":listaAntecesores}        
    return response
    